import { useEffect, useMemo, useState, type CSSProperties } from 'react';
import './TestPage.css';

type DeviceInfo = {
  index: number;
  label: string;
  sn: string;
};

type CertInfo = {
  subjectCN: string;
  issuerCN: string;
  serial: string;
  usageText: string;
  validFrom: string;
  validTo: string;
  algorithm: string;
};

const ensureZjcaReady = () => {
  if ((window as any).g_ZjcaCMT) return true;
  const ctor = (window as any).zjca_CMT;
  if (!ctor) return false;
  const attempt = (protocol: 'https' | 'http') => {
    try {
      const instance = new ctor(() => {}, null);
      instance.setProtocol(protocol);
      const resp = instance.init(1, 1);
      if (resp?.code === 0) {
        (window as any).g_ZjcaCMT = instance;
        return true;
      }
    } catch (error) {
      console.warn(`使用 ${protocol.toUpperCase()} 初始化 ZJCA 失败:`, error);
    }
    return false;
  };
  return attempt('https') || attempt('http');
};

const useZjcaReady = () => {
  const [ready, setReady] = useState(false);
  useEffect(() => {
    setReady(ensureZjcaReady());
  }, []);
  return ready;
};

const describeDevice = (key: any): DeviceInfo => ({
  index: typeof key.getIndex === 'function' ? key.getIndex() : key.index ?? -1,
  label: typeof key.getLabel === 'function' ? key.getLabel() : key.label ?? '未知介质',
  sn: typeof key.getSN === 'function' ? key.getSN() : key.sn ?? '',
});

const formatFileName = (path: string) => (path ? path.split(/[/\\]/).pop() || path : '');

const SignaturePage = () => {
  const ready = useZjcaReady();
  const zjca = useMemo(() => (window as any).g_ZjcaCMT, [ready]);

  const [devices, setDevices] = useState<DeviceInfo[]>([]);
  const [deviceIndex, setDeviceIndex] = useState<number>(-1);

  const [selectedFilePath, setSelectedFilePath] = useState('');
  const [selectedFileName, setSelectedFileName] = useState('');
  const [signing, setSigning] = useState(false);
  const [lastSignedPath, setLastSignedPath] = useState('');

  const [verifyOriginalPath, setVerifyOriginalPath] = useState('');
  const [verifyOriginalName, setVerifyOriginalName] = useState('');
  const [verifySignaturePath, setVerifySignaturePath] = useState('');
  const [verifySignatureName, setVerifySignatureName] = useState('');

  const [signatureBase64, setSignatureBase64] = useState('');
  const [signatureCertInfo, setSignatureCertInfo] = useState<CertInfo | null>(null);
  const [signatureTimestamp, setSignatureTimestamp] = useState('');

  const [verificationStatus, setVerificationStatus] =
    useState<'idle' | 'success' | 'error'>('idle');
  const [verificationMessage, setVerificationMessage] = useState('');
  const [verifying, setVerifying] = useState(false);

  const [verifyMode, setVerifyMode] = useState<'device' | 'cert'>('device');
  const [verifyDeviceIndex, setVerifyDeviceIndex] = useState<number>(-1);

  useEffect(() => {
    if (!ready || !zjca) {
      setDevices([]);
      setDeviceIndex(-1);
      return;
    }
    try {
      const resp = zjca.getKeyList(false);
      if (resp?.code === 0 && Array.isArray(resp.res)) {
        const list = resp.res.map((key: any) => describeDevice(key));
        setDevices(list);
        setDeviceIndex((prev) =>
          prev >= 0 && list.some((item: DeviceInfo) => item.index === prev) ? prev : list[0]?.index ?? -1,
        );
        setVerifyDeviceIndex((prev) =>
          prev >= 0 && list.some((item: DeviceInfo) => item.index === prev) ? prev : list[0]?.index ?? -1,
        );
      } else {
        setDevices([]);
        setDeviceIndex(-1);
        setVerifyDeviceIndex(-1);
      }
    } catch (error) {
      console.warn('枚举介质失败:', error);
      setDevices([]);
      setDeviceIndex(-1);
      setVerifyDeviceIndex(-1);
    }
  }, [ready, zjca]);

  const decodeCertInfo = (certBase64: string): CertInfo | null => {
    if (!zjca || !certBase64) return null;
    let handle: any = null;
    try {
      const resp = zjca.decodeCert(certBase64);
      if (resp?.code !== 0 || !resp.res) return null;
      handle = resp.res;
      const getAttr = (key: string, param = '') => {
        const attr = zjca.getCertAttribute(handle, key, param);
        return attr?.code === 0 ? attr.res : '';
      };
      const usage = Number(getAttr('cert_usage'));
      const usageText = usage === 1 ? '签名' : usage === 2 ? '加密' : '未知';
      const valid = zjca.getCertAttribute(handle, 'cert_validdate', '')?.res;
      const alg = Number(getAttr('cert_keyalg'));
      let algorithm = '未知';
      if (alg === 1) algorithm = 'RSA';
      else if (alg === 2) algorithm = 'SM2(国密)';
      else if (alg) algorithm = `${alg}`;
      return {
        subjectCN: getAttr('cert_subject', 'CN=') || getAttr('cert_subject') || '未知',
        issuerCN: getAttr('cert_issuer', 'CN=') || getAttr('cert_issuer') || '未知',
        serial: getAttr('cert_sn') || '未知',
        usageText,
        validFrom: valid?.fromDate || '未知',
        validTo: valid?.endDate || '未知',
        algorithm,
      };
    } catch (error) {
      console.warn('解析证书失败:', error);
      return null;
    } finally {
      if (handle) {
        try {
          zjca.releaseCert(handle);
        } catch (releaseError) {
          console.warn('释放证书句柄失败:', releaseError);
        }
      }
    }
  };

  const loadSignatureSummary = (path: string, base64?: string) => {
    if (!path || !zjca) return;
    try {
      let content = base64;
      if (!content) {
        const resp = zjca.readFile(path, true);
        if (resp?.code !== 0 || !resp.res) {
          throw new Error(resp?.msg || '读取签名文件失败');
        }
        content = resp.res as string;
      }
      setSignatureBase64(content);
      const attached = zjca.getSignatureAttached(content);
      if (attached?.code === 0 && attached.res) {
        setSignatureTimestamp(attached.res.time || '');
        if (attached.res.cert) {
          setSignatureCertInfo(decodeCertInfo(attached.res.cert));
        } else {
          setSignatureCertInfo(null);
        }
      } else {
        setSignatureTimestamp('');
        setSignatureCertInfo(null);
      }
    } catch (error) {
      console.warn('解析签名文件失败:', error);
      setSignatureBase64('');
      setSignatureTimestamp('');
      setSignatureCertInfo(null);
    }
  };

  const browseFileToSign = () => {
    if (!ready || !zjca) {
      alert('ZJCA 客户端未初始化，请先返回首页完成初始化。');
      return;
    }
    const resp = zjca.getFileName(true, '选择需要签名的文件', '*.*');
    if (resp?.code === 0 && resp.res) {
      setSelectedFilePath(resp.res as string);
      setSelectedFileName(formatFileName(resp.res as string));
    }
  };

  const handleSignFile = () => {
    if (!ready || !zjca) {
      alert('ZJCA 客户端未初始化，请先返回首页完成初始化。');
      return;
    }
    if (deviceIndex < 0) {
      alert('请先选择用于签名的介质。');
      return;
    }
    if (!selectedFilePath) {
      alert('请选择要签名的文件。');
      return;
    }
    try {
      const pinResp = zjca.verifyPin(deviceIndex, '');
      if (pinResp?.code !== 0) {
        alert(`PIN 验证失败：${pinResp?.msg || pinResp?.code || '未知错误'}`);
        return;
      }
    } catch (error: any) {
      alert(`PIN 验证异常：${error?.message || error}`);
      return;
    }

    try {
      setSigning(true);
      const signResp = zjca.signFileUseKey(deviceIndex, 0, 2, 0x05, selectedFilePath, null, null);
      if (!signResp || signResp.code !== 0 || !signResp.res) {
        alert(`签名失败：${signResp?.msg || '未知错误'}`);
        return;
      }

      const suggest = `${selectedFileName || 'signed'}.p7s`;
      const saveResp = zjca.getFileName(false, `保存签名文件（建议：${suggest}）`, '*.p7s');
      if (saveResp?.code !== 0 || !saveResp.res) return;
      let targetPath = saveResp.res as string;
      if (!targetPath.toLowerCase().endsWith('.p7s')) {
        targetPath = `${targetPath}.p7s`;
      }
      const writeResp = zjca.writeFile(targetPath, signResp.res, true);
      if (writeResp?.code !== 0) {
        alert(`写入签名文件失败：${writeResp?.msg || '未知错误'}`);
        return;
      }

      setLastSignedPath(targetPath);
      setVerifyOriginalPath(selectedFilePath);
      setVerifyOriginalName(selectedFileName);
      setVerifySignaturePath(targetPath);
      setVerifySignatureName(formatFileName(targetPath));
      loadSignatureSummary(targetPath, signResp.res as string);
      alert(`签名成功！\n签名文件：${targetPath}`);
    } catch (error: any) {
      alert(`签名异常：${error?.message || error}`);
    } finally {
      setSigning(false);
    }
  };

  const browseOriginalForVerify = () => {
    if (!ready || !zjca) {
      alert('ZJCA 客户端未初始化，请先返回首页完成初始化。');
      return;
    }
    const resp = zjca.getFileName(true, '选择原文文件', '*.*');
    if (resp?.code === 0 && resp.res) {
      setVerifyOriginalPath(resp.res as string);
      setVerifyOriginalName(formatFileName(resp.res as string));
      setVerificationStatus('idle');
      setVerificationMessage('');
    }
  };

  const browseSignatureForVerify = () => {
    if (!ready || !zjca) {
      alert('ZJCA 客户端未初始化，请先返回首页完成初始化。');
      return;
    }
    const resp = zjca.getFileName(true, '选择签名文件 (.p7s/.p7m)', '*.p7s;*.p7m;*.*');
    if (resp?.code === 0 && resp.res) {
      setVerifySignaturePath(resp.res as string);
      setVerifySignatureName(formatFileName(resp.res as string));
      setVerificationStatus('idle');
      setVerificationMessage('');
      loadSignatureSummary(resp.res as string);
    }
  };

  const ensureSignatureData = (path: string) => {
    if (!zjca) throw new Error('ZJCA 客户端未初始化');
    if (signatureBase64 && verifySignaturePath && path === verifySignaturePath) {
      return signatureBase64;
    }
    const resp = zjca.readFile(path, true);
    if (resp?.code !== 0 || !resp.res) {
      throw new Error(resp?.msg || '读取签名文件失败');
    }
    const base64 = resp.res as string;
    loadSignatureSummary(path, base64);
    return base64;
  };

  const handleVerifySignature = () => {
    if (!ready || !zjca) {
      alert('ZJCA 客户端未初始化，请先返回首页完成初始化。');
      return;
    }
    if (!verifyOriginalPath) {
      alert('请选择原文文件。');
      return;
    }
    if (!verifySignaturePath) {
      alert('请选择签名文件。');
      return;
    }
    try {
      setVerifying(true);
      const base64 = ensureSignatureData(verifySignaturePath);
      let certBase64 = signatureCertInfo ? (signatureBase64 ? zjca.getSignatureAttached(signatureBase64)?.res?.cert || '' : '') : '';
      if (!certBase64) {
        const attached = zjca.getSignatureAttached(base64);
        if (attached?.code === 0 && attached.res?.cert) {
          certBase64 = attached.res.cert;
          setSignatureCertInfo(decodeCertInfo(certBase64));
        }
      }
      let keyIndex = -1;
      if (verifyMode === 'device') {
        if (verifyDeviceIndex < 0) {
          alert('请先选择用于验证的介质。');
          return;
        }
        keyIndex = verifyDeviceIndex;
        certBase64 = '';
      } else if (!certBase64) {
        alert('签名文件未包含证书，无法使用“证书验证”模式。');
        return;
      }
      const verifyResp = zjca.verifyFile(keyIndex, verifyOriginalPath, base64, certBase64, null, null);
      if (verifyResp?.code === 0) {
        setVerificationStatus('success');
        setVerificationMessage('签名验证通过，原文未被篡改。');
      } else {
        setVerificationStatus('error');
        setVerificationMessage(`签名验证失败：${verifyResp?.msg || verifyResp?.code || '未知错误'}`);
      }
    } catch (error: any) {
      setVerificationStatus('error');
      setVerificationMessage(error?.message || String(error));
    } finally {
      setVerifying(false);
    }
  };

  const panelStyle: CSSProperties = {
    padding: 24,
    borderRadius: 20,
    background: '#fff',
    boxShadow: '0 18px 40px rgba(0,0,0,0.12)',
    marginBottom: 24,
  };

  const buttonStyleFn = (enabled: boolean, color: string): CSSProperties => ({
    padding: '10px 22px',
    borderRadius: 24,
    border: 'none',
    color: '#fff',
    fontWeight: 600,
    cursor: enabled ? 'pointer' : 'not-allowed',
    opacity: enabled ? 1 : 0.45,
    background: color,
    boxShadow: enabled ? `0 6px 16px ${color}33` : 'none',
  });

  const renderDeviceSelector = () => (
    <div
      style={{
        marginBottom: 16,
        padding: 12,
        borderRadius: 12,
        background: '#eef2ff',
        display: 'flex',
        flexWrap: 'wrap',
        gap: 12,
        alignItems: 'center',
      }}
    >
      <span style={{ fontWeight: 600, color: '#1e3a8a' }}>签名介质</span>
      <select
        value={deviceIndex >= 0 ? deviceIndex : ''}
        onChange={(e) => setDeviceIndex(Number(e.target.value))}
        style={{ minWidth: 220, padding: '8px 12px', borderRadius: 8 }}
      >
        {devices.length === 0 && <option value="">未检测到介质</option>}
        {devices.length > 0 && <option value="">请选择介质</option>}
        {devices.map((device) => (
          <option key={device.index} value={device.index}>
            {device.label}
            {device.sn ? ` (${device.sn})` : ''}
          </option>
        ))}
      </select>
    </div>
  );

  const signatureInfoBlock = () => {
    if (!signatureCertInfo && !signatureTimestamp) return null;
    return (
      <div
        style={{
          marginTop: 12,
          padding: 16,
          borderRadius: 12,
          background: '#f3f4f6',
          fontSize: 13,
          color: '#1f2937',
          lineHeight: 1.7,
        }}
      >
        {signatureTimestamp && <div>签名时间：{signatureTimestamp}</div>}
        {signatureCertInfo ? (
          <>
            <div>证书主题：{signatureCertInfo.subjectCN}</div>
            <div>颁发者：{signatureCertInfo.issuerCN}</div>
            <div>序列号：{signatureCertInfo.serial}</div>
            <div>
              用途：{signatureCertInfo.usageText} | 算法：{signatureCertInfo.algorithm}
            </div>
            <div>
              有效期：{signatureCertInfo.validFrom} - {signatureCertInfo.validTo}
            </div>
          </>
        ) : (
          <div>该签名文件未携带证书信息。</div>
        )}
      </div>
    );
  };

  return (
    <div
      className="test-page"
      style={{
        minHeight: '100vh',
        background: 'linear-gradient(135deg,#5c6bc0 0%,#1e88e5 100%)',
        padding: 24,
      }}
    >
      <div
        className="test-container"
        style={{
          maxWidth: 920,
          margin: '0 auto',
          background: 'rgba(255,255,255,0.97)',
          borderRadius: 28,
          padding: 32,
          boxShadow: '0 26px 70px rgba(0,0,0,0.25)',
        }}
      >
        <div style={panelStyle}>
          <h2>🖊️ 文件签名（PKCS#7）</h2>
          <p style={{ color: '#4b5563', lineHeight: 1.6 }}>
            选择任意文件并使用介质中的签名证书生成 .p7s 签名，同时支持查看签名所使用的证书信息。
          </p>
          {!ready && (
            <div
              style={{
                marginBottom: 12,
                padding: 12,
                borderRadius: 10,
                background: '#fff3e0',
                color: '#c65302',
              }}
            >
              未检测到 ZJCA 客户端，请返回首页完成初始化后再使用签名功能。
            </div>
          )}
          {renderDeviceSelector()}
          <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', marginBottom: 12 }}>
            <button style={buttonStyleFn(true, '#1d4ed8')} onClick={browseFileToSign}>
              选择签名文件
            </button>
            <button
              style={buttonStyleFn(!selectedFilePath || !ready || signing ? false : true, '#fb8c00')}
              disabled={!selectedFilePath || !ready || signing}
              onClick={handleSignFile}
            >
              {signing ? '签名中...' : '执行签名'}
            </button>
          </div>
          {selectedFileName && (
            <div style={{ color: '#1f2937', fontSize: 13 }}>原文件：{selectedFileName}</div>
          )}
          {lastSignedPath && (
            <div style={{ marginTop: 8, color: '#15803d', fontSize: 13 }}>
              最近签名文件：{lastSignedPath}
            </div>
          )}
        </div>

        <div style={panelStyle}>
          <h2>🔍 文件签名验证</h2>
          <p style={{ color: '#4b5563', lineHeight: 1.6 }}>
            选择原文和签名文件即可验证签名有效性，并查看签名中的证书/时间戳信息。
          </p>
          <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', marginBottom: 10 }}>
            <button
              style={buttonStyleFn(!!ready, '#059669')}
              disabled={!ready}
              onClick={browseOriginalForVerify}
            >
              选择原文文件
            </button>
            {verifyOriginalName && (
              <span style={{ color: '#14532d', fontSize: 13 }}>原文：{verifyOriginalName}</span>
            )}
          </div>
          <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', marginBottom: 10 }}>
            <button
              style={buttonStyleFn(!!ready, '#7c3aed')}
              disabled={!ready}
              onClick={browseSignatureForVerify}
            >
              选择签名文件(.p7s/.p7m)
            </button>
            {verifySignatureName && (
              <span style={{ color: '#4c1d95', fontSize: 13 }}>签名：{verifySignatureName}</span>
            )}
          </div>
          <div style={{ margin: '10px 0', display: 'flex', gap: 12, flexWrap: 'wrap' }}>
            <button
              style={buttonStyleFn(true, verifyMode === 'device' ? '#2563eb' : '#cbd5f5')}
              onClick={() => setVerifyMode('device')}
            >
              使用介质验证
            </button>
            <button
              style={buttonStyleFn(true, verifyMode === 'cert' ? '#d97706' : '#fde68a')}
              onClick={() => setVerifyMode('cert')}
            >
              使用签名证书验证
            </button>
          </div>
          {verifyMode === 'device' && (
            <div style={{ marginBottom: 12 }}>
              <span style={{ fontSize: 13, marginRight: 8 }}>验证介质：</span>
              <select
                value={verifyDeviceIndex >= 0 ? verifyDeviceIndex : ''}
                onChange={(e) =>
                  setVerifyDeviceIndex(e.target.value === '' ? -1 : Number(e.target.value))
                }
                style={{ minWidth: 220, padding: '8px 12px', borderRadius: 8 }}
              >
                <option value="">请选择介质</option>
                {devices.map((device) => (
                  <option key={device.index} value={device.index}>
                    {device.label}
                    {device.sn ? ` (${device.sn})` : ''}
                  </option>
                ))}
              </select>
            </div>
          )}
          <button
            style={buttonStyleFn(
              !verifyOriginalPath || !verifySignaturePath || !ready || verifying ? false : true,
              '#ea580c',
            )}
            disabled={!verifyOriginalPath || !verifySignaturePath || !ready || verifying}
            onClick={handleVerifySignature}
          >
            {verifying ? '验证中...' : '执行验证'}
          </button>
          {verificationStatus !== 'idle' && (
            <div
              style={{
                marginTop: 12,
                padding: 12,
                borderRadius: 10,
                background: verificationStatus === 'success' ? '#e8f5e9' : '#ffebee',
                color: verificationStatus === 'success' ? '#166534' : '#b91c1c',
              }}
            >
              {verificationMessage}
            </div>
          )}
          {signatureInfoBlock()}
        </div>
      </div>
    </div>
  );
};

export default SignaturePage;
